import TransformManager from './TransformManager';
import type {
  BoundingBox,
  GraphicObjectData,
  GraphicStyle,
  Point,
  Transform,
  ViewTransform,
} from './types';
import { GraphicType } from './types';

// 图形对象基类
export abstract class GraphicObject {
  public readonly id: string;
  public readonly type: GraphicType;
  public transform: Transform;
  public style: GraphicStyle;
  public layerId: string;

  constructor(
    type: GraphicType,
    transform: Transform = GraphicObject.defaultTransform(),
    style: GraphicStyle = GraphicObject.defaultStyle(),
    layerId: string = 'default',
  ) {
    this.id = this.generateId();
    this.type = type;
    this.transform = transform;
    this.style = style;
    this.layerId = layerId;
  }

  // 抽象方法 - 必须由子类实现
  abstract draw(
    ctx: CanvasRenderingContext2D,
    viewTransform: ViewTransform,
  ): void;
  abstract contains(point: Point): boolean;
  abstract getBoundingBox(): BoundingBox;

  // 变换操作
  translate(delta: Point): void {
    // 创建平移变换
    const translationTransform: Transform = {
      position: delta,
      rotation: 0,
      scale: { x: 1, y: 1 },
      anchor: { x: 0.5, y: 0.5 },
    };

    // 使用TransformManager组合变换
    this.transform = TransformManager.compose(
      this.transform,
      translationTransform,
    );
  }

  rotate(angle: number, center?: Point): void {
    const centerPoint = center || this.getCenter();

    // 创建旋转变换
    const rotationTransform: Transform = {
      position: { x: 0, y: 0 },
      rotation: angle,
      scale: { x: 1, y: 1 },
      anchor: { x: 0.5, y: 0.5 },
    };

    // 计算相对于中心点的变换
    const relativeTransform: Transform = {
      position: { x: centerPoint.x, y: centerPoint.y },
      rotation: 0,
      scale: { x: 1, y: 1 },
      anchor: { x: 0.5, y: 0.5 },
    };

    // 使用TransformManager组合变换：先移动到中心点，旋转，再移动回原位置
    const moveToCenter = TransformManager.compose(
      relativeTransform,
      this.transform,
    );
    const rotateAtCenter = TransformManager.compose(
      rotationTransform,
      moveToCenter,
    );
    const moveBack = TransformManager.compose(
      TransformManager.inverse(relativeTransform),
      rotateAtCenter,
    );

    this.transform = moveBack;
  }

  scale(scaleX: number, scaleY: number, center?: Point): void {
    const centerPoint = center || this.getCenter();

    // 创建缩放变换
    const scaleTransform: Transform = {
      position: { x: 0, y: 0 },
      rotation: 0,
      scale: { x: scaleX, y: scaleY },
      anchor: { x: 0.5, y: 0.5 },
    };

    // 计算相对于中心点的变换
    const relativeTransform: Transform = {
      position: { x: centerPoint.x, y: centerPoint.y },
      rotation: 0,
      scale: { x: 1, y: 1 },
      anchor: { x: 0.5, y: 0.5 },
    };

    // 使用TransformManager组合变换：先移动到中心点，缩放，再移动回原位置
    const moveToCenter = TransformManager.compose(
      relativeTransform,
      this.transform,
    );
    const scaleAtCenter = TransformManager.compose(
      scaleTransform,
      moveToCenter,
    );
    const moveBack = TransformManager.compose(
      TransformManager.inverse(relativeTransform),
      scaleAtCenter,
    );

    this.transform = moveBack;
  }

  // 获取中心点
  getCenter(): Point {
    const bbox = this.getBoundingBox();
    return {
      x: bbox.x + bbox.width / 2,
      y: bbox.y + bbox.height / 2,
    };
  }

  /**
   * 获取变换矩阵
   */
  getTransformMatrix(): DOMMatrix {
    const matrix = new DOMMatrix();
    matrix.translateSelf(this.transform.position.x, this.transform.position.y);
    matrix.rotateSelf(0, 0, this.transform.rotation);
    matrix.scaleSelf(this.transform.scale.x, this.transform.scale.y);
    return matrix;
  }

  /**
   * 序列化对象数据
   */
  serialize(): GraphicObjectData {
    return {
      id: this.id,
      type: this.type,
      transform: { ...this.transform },
      style: { ...this.style },
      layerId: this.layerId,
    };
  }

  // 静态方法
  static defaultTransform(): Transform {
    return {
      position: { x: 0, y: 0 },
      rotation: 0,
      scale: { x: 1, y: 1 },
      anchor: { x: 0.5, y: 0.5 },
    };
  }

  static defaultStyle(): GraphicStyle {
    return {
      fillColor: '#3498db',
      strokeColor: '#2980b9',
      strokeWidth: 2,
      opacity: 1,
    };
  }

  // 生成唯一ID
  private generateId(): string {
    return `${this.type}_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
  }
}

export { GraphicType };

export type { ViewTransform, BoundingBox, Point };
